#include "game.h"
#include "animated_graphic.h"
#include "game_object_factory.h"
#include "game_over_state.h"
#include "input_handler.h"
#include "main_menu_state.h"
#include "menu_button.h"
#include "sound_manager.h"
#include "texture_manager.h"
#include <iostream>

Game* Game::s_pInstance = NULL;

Game::Game():
    m_pWindow(NULL),
    m_pRenderer(NULL),
    m_bRunning(false),
    m_pGameStateMachine(NULL),
    m_bLevelComplete(false)
{    
    // start at this level
    m_currentLevel = 1;
}

Game::~Game()
{
    // we must clean up after ourselves to prevent memory leaks
    m_pRenderer = NULL;
    m_pWindow = NULL;
}


bool Game::init(const char* title, int xpos, int ypos, int width, int height, bool fullscreen)
{
    int flags = NULL;
    
    // store the game width and height
    m_gameWidth = width;
    m_gameHeight = height;
    
    if (fullscreen)
    {
        flags = SDL_WINDOW_FULLSCREEN;
    }
    
    // attempt to initialise SDL
    if (SDL_Init(SDL_INIT_EVERYTHING) == NULL)
    {
        std::cout << "SDL init success\n";
        // init the window
        m_pWindow = SDL_CreateWindow(title, xpos, ypos, width, height, flags);
        
        if (m_pWindow != NULL) // window init success
        {
            std::cout << "window creation success\n";
            m_pRenderer = SDL_CreateRenderer(m_pWindow, -1, SDL_RENDERER_ACCELERATED);
            
            if (m_pRenderer != NULL) // renderer init success
            {
                std::cout << "renderer creation success\n";
                SDL_SetRenderDrawColor(m_pRenderer, 0, 0, 0, 255);
            }
            else
            {
                std::cout << "renderer init fail\n";
                return false; // renderer init fail
            }
        }
        else
        {
            std::cout << "window init fail\n";
            return false; // window init fail
        }
    }
    else
    {
        std::cout << "SDL init fail\n";
        return false; // SDL init fail
    }
    
    // add some sound effects - TODO move to better place
    TheSoundManager::Instance()->load("music/DST-Away.ogg", "music1", SOUND_MUSIC);
    TheSoundManager::Instance()->load("sounds/jump.wav", "jump", SOUND_SFX);
    
    TheSoundManager::Instance()->playMusic("music1", -1);
       
    TheInputHandler::Instance()->initialiseJoysticks();
    
    // register the types for the game
    TheGameObjectFactory::Instance()->registerType("MenuButton", new MenuButtonCreator());
    TheGameObjectFactory::Instance()->registerType("AnimatedGraphic", new AnimatedGraphicCreator());
    
    // start the menu state
    m_pGameStateMachine = new GameStateMachine();
    m_pGameStateMachine->changeState(new MainMenuState());
    
    m_bRunning = true; // everything inited successfully, start the main loop
    return true;
}

void Game::setCurrentLevel(int currentLevel)
{
    m_currentLevel = currentLevel;
    m_pGameStateMachine->changeState(new GameOverState());
    m_bLevelComplete = false;
}

void Game::render()
{
    SDL_RenderClear(m_pRenderer);
    
    m_pGameStateMachine->render();
    
    SDL_RenderPresent(m_pRenderer);
}

void Game::update()
{
    m_pGameStateMachine->update();
}

void Game::handleEvents()
{
    TheInputHandler::Instance()->update();
}

void Game::clean()
{
    std::cout << "cleaning game\n";
    
    TheInputHandler::Instance()->clean();
    
    m_pGameStateMachine->clean();
    
    //m_pGameStateMachine = 0;
    delete m_pGameStateMachine;
    m_pGameStateMachine = NULL;
    
    TheTextureManager::Instance()->clearTextureMap();
    
    SDL_DestroyWindow(m_pWindow);
    SDL_DestroyRenderer(m_pRenderer);
    SDL_Quit();
}
